package com.omuao.cloud.stabilization.common.message.core.config;

import com.omuao.cloud.stabilization.common.message.annotation.MessageQueue;
import org.aopalliance.aop.Advice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.Pointcut;
import org.springframework.aop.PointcutAdvisor;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * 消息队列初始化处理器，对所有带有 MessageQueue 注解的进行范围增强
 *
 * @author omuao
 */
public class MessageQueueInitializationPostProcessor implements ApplicationContextAware, BeanPostProcessor {

    public static Logger logger = LoggerFactory.getLogger(MessageQueueInitializationPostProcessor.class);

    private ApplicationContext applicationContext;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean == null) {
            return null;
        }

        if (!bean.getClass().isAnnotationPresent(MessageQueue.class)) {
            //对已经采用AOP增强的则额外判断
            if (AopUtils.isAopProxy(bean)) {
                if (!AopUtils.getTargetClass(bean.getClass()).isAnnotationPresent(MessageQueue.class)) {
                    return bean;
                }
            } else {
                return bean;
            }
        }

        Pointcut pointcut = new MessageQueuePointcut();

        Advice advice = new MessageQueueProcessor(applicationContext);

        PointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

        ProxyFactory weaver = new ProxyFactory();
        //指定代理目标对象
        weaver.setTarget(bean);
        //指定方面
        weaver.addAdvisor(advisor);

        return weaver.getProxy();
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}